#ifndef GAME_DEBUG_VARIABLE_H
#define GAME_DEBUG_VARIABLE_H
#include "game_platform.h"

#include "game_debug.h"

#define DEBUG_MAX_VARIABLE_STACK_DEPTH 64
struct debug_variable_link {
    debug_variable_link* Next;
    debug_variable_link* Prev;

    debug_variable_link* FirstChild;
    debug_variable_link* LastChild;
    debug_element* Element;
    char* Name;
};

inline debug_variable_link* GetSentinel(debug_variable_link* From) {
    debug_variable_link* Result = (debug_variable_link*)&From->FirstChild;
    return Result;
}

inline bool32 HasChildren(debug_variable_link* Link) {
    bool32 Result = (Link->FirstChild != GetSentinel(Link));
    return Result;
}
struct debug_event_array {
    uint32 Count;
    debug_event* Vars;
};

#if 0
struct debug_variable_definition_context {
    debug_state* State;
    memory_arena* Arena;
    uint32 GroupDepth;
    debug_variable* GroupStack[64];
};

internal debug_variable* DEBUGAddVariable(debug_state* DebugState, debug_variable_type Type,
                                          const char* Name) {
    debug_variable* Var = PushStruct(&DebugState->DebugArena, debug_variable);
    Var->Type = Type;
    Var->Name = (const char*)PushCopy(&DebugState->DebugArena, StringLength(Name) + 1, (void*)Name);
    return Var;
}
internal void DebugAddVariableToGroup(debug_state* DebugState, debug_variable* Group,
                                      debug_variable* Add) {
    debug_variable_link* Link = PushStruct(&DebugState->DebugArena, debug_variable_link);
    DLIST_INSERT(&Group->VarGroup, Link);
    Link->Var = Add;
}

internal void DEBUGAddVariableToDefaultGroup(debug_variable_definition_context* Context,
                                             debug_variable* Var) {
    debug_variable* Parent = Context->GroupStack[Context->GroupDepth];
    if (Parent) {
        DebugAddVariableToGroup(Context->State, Parent, Var);
    }
}

internal debug_variable* DEBUGAddRootGroup(debug_state* DebugState, const char* Name) {
    debug_variable* Group = DEBUGAddVariable(DebugState, DebugVariableType_VarGroup, Name);
    DLIST_INIT(&Group->VarGroup);
    return Group;
}

internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          debug_variable_type Type, const char* Name) {
    debug_variable* Var = DEBUGAddVariable(Context->State, Type, Name);
    debug_variable* Parent = Context->GroupStack[Context->GroupDepth];
    if (Parent) {
        DebugAddVariableToGroup(Context->State, Parent, Var);
    }
    return Var;
}

struct debug_variable_link_builder {
    debug_variable* ParentGroup;
    debug_variable* Group;
};

internal debug_variable* DEBUGBeginVariableGroup(debug_variable_definition_context* Context,
                                                 const char* Name) {
    debug_variable* Group = DEBUGAddRootGroup(Context->State, Name);
    DEBUGAddVariableToDefaultGroup(Context, Group);
    Assert(Context->GroupDepth < ArrayCount(Context->GroupStack) - 1);
    Context->GroupStack[++Context->GroupDepth] = Group;
    return Group;
}
internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          const char* Name, bool32 Varible) {
    debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_Boolean, Name);
    Var->Bool32 = Varible;
    return Var;
}
internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          const char* Name, uint32 Varible) {
    debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_Uint32, Name);
    Var->Uint32 = Varible;
    return Var;
}

internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          const char* Name, bitmap_id Value) {
    debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_BitmapDisplay, Name);
    Var->BitmapDisplay.BitmapID = Value;
    return Var;
}

// internal void DEBUGAddVariable(debug_variable_definition_context* Context, const char* Name,
//                                int32 Varible) {
//     debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_Boolean, Name);
//     Var->Int32 = Varible;
// }
internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          const char* Name, real32 Varible) {
    debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_Real32, Name);
    Var->Real32 = Varible;
    return Var;
}
internal debug_variable* DEBUGAddVariable(debug_variable_definition_context* Context,
                                          const char* Name, v4 Varible) {
    debug_variable* Var = DEBUGAddVariable(Context, DebugVariableType_V4, Name);
    Var->Vector4 = Varible;
    return Var;
}
internal void DEBUGEndVariableGroup(debug_variable_definition_context* Context) {
    Assert(Context->GroupDepth > 0);
    --Context->GroupDepth;
}
internal void DEBUGCreateVariables(debug_variable_definition_context* Context) {
#define DEBUG_VARIABLE_LISTING(Name) DEBUGAddVariable(Context, #Name, DEBUGUI_##Name)

    DEBUGBeginVariableGroup(Context, "Entities");
    DEBUG_VARIABLE_LISTING(DrawEntityOutline);
    DEBUGEndVariableGroup(Context);

    DEBUGBeginVariableGroup(Context, "Chunks");
    DEBUG_VARIABLE_LISTING(GroundChunkOutlines);
    DEBUG_VARIABLE_LISTING(GroundChunkCheckerboards);
    DEBUG_VARIABLE_LISTING(RecomputeGroundChunkOnEXEChange);
    DEBUGEndVariableGroup(Context);

    DEBUGBeginVariableGroup(Context, "Particles");
    DEBUG_VARIABLE_LISTING(ParticleTest);
    DEBUG_VARIABLE_LISTING(ParticleGrid);
    DEBUGEndVariableGroup(Context);

    DEBUGBeginVariableGroup(Context, "Renderer");
    {
        DEBUG_VARIABLE_LISTING(TestWeirdRrawBufferSize);
        DEBUG_VARIABLE_LISTING(ShowLightingSamples);
        {
            DEBUGBeginVariableGroup(Context, "Camera");
            {
                DEBUG_VARIABLE_LISTING(UseDebugCamera);
                DEBUG_VARIABLE_LISTING(UseRoomBaseCamera);
                DEBUG_VARIABLE_LISTING(DebugCameraDistance);
            }
            DEBUGEndVariableGroup(Context);
        }
    }
    DEBUGEndVariableGroup(Context);

    DEBUG_VARIABLE_LISTING(FamiliarFollowsHero);
    DEBUG_VARIABLE_LISTING(UseSpacesOutlines);
    DEBUG_VARIABLE_LISTING(FauxV4);

#undef DEBUG_VARIABLE_LISTING
}
#endif
#endif